package com.weixing.mall.provider.controller;

import com.weixing.mall.base.constant.GlobalConstant;
import com.weixing.mall.base.enums.IsEnableEnum;
import com.weixing.mall.base.enums.ResultCodeEnum;
import com.weixing.mall.base.enums.SysCfgCodeEnum;
import com.weixing.mall.base.wrapper.Result;
import com.weixing.mall.base.wrapper.ResultUtil;
import com.weixing.mall.core.annotation.Frequency;
import com.weixing.mall.core.annotation.NoNeedAccess;
import com.weixing.mall.core.support.BaseController;
import com.weixing.mall.core.support.auth.AuthUtil;
import com.weixing.mall.core.support.auth.MemAuth;
import com.weixing.mall.core.support.msg.*;
import com.weixing.mall.core.utils.CommonUtil;
import com.weixing.mall.core.validation.Mobile;
import com.weixing.mall.provider.api.model.vo.AgentVo;
import com.weixing.mall.provider.api.model.vo.SysConfigVo;
import com.weixing.mall.provider.api.service.AgentServiceRpc;
import com.weixing.mall.provider.api.service.SysConfigServiceFeign;
import com.weixing.mall.provider.model.domain.Member;
import com.weixing.mall.provider.model.dto.MemberChgPwdDto;
import com.weixing.mall.provider.model.dto.RegisterDto;
import com.weixing.mall.provider.model.dto.ResetPwdDto;
import com.weixing.mall.provider.model.dto.SendMsgDto;
import com.weixing.mall.provider.service.IMemberService;
import com.weixing.mall.util.ThreadLocalMap;
import jodd.util.StringUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

/**
 * 会员注册登录相关Api
 *
 * @author  kfc
 * @since v1
 */
@Validated
@RestController
@RequestMapping("passport")
public class PassportController extends BaseController {

    @Autowired
    private IMemberService memberService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private SysConfigServiceFeign sysConfigService;
    @Autowired
    private AgentServiceRpc agentServiceRpc;

    /**
     * 校验手机号是否可用
     * @param mobile 手机号
     * @return 校验结果
     */
    @GetMapping("checkMobile")
    @NoNeedAccess
    public Result checkMobile(@Mobile(message = "请填写正确的手机号格式") String mobile) {
        return memberService.checkMobileExist(mobile) ? ResultUtil.error(ResultCodeEnum.CODE_10012004) : ResultUtil.success();
    }

    /**
     * 校验是否开启会员绑定代理商功能
     * @return 校验结果
     */
    @GetMapping("checkAgentBind")
    public Result checkAgentBind() {
        Result<SysConfigVo> result = sysConfigService.getByCode(SysCfgCodeEnum.MEMBER_BIND_AGENT.getCode());
        if (result.isSuccess()) {
            if (1 == result.getData().getCfgValue()) {
                return ResultUtil.success();
            }
        }
        return ResultUtil.error();
    }


    /**
     * 发送短信
     * @param dto      发送短信参数
     * @param request  HttpServletRequest
     * @return  结果
     */
    @Frequency
    @PostMapping("sendMsg")
    @NoNeedAccess
    public Result sendRegisterMsg(@RequestBody SendMsgDto dto, HttpServletRequest request) {
        // 判断是否需要发送短息
        boolean msgSendSuccess = false;
        Result result = handlerBizCheck(dto.getBizCode(), dto.getMobile());
        if (!result.isSuccess()) {
            return result;
        }
        // 校验图形验证码是否正确
        result = sendMsg(dto.getMobile(), dto.getImageCode(), dto.getBizCode(), request);
        msgSendSuccess = result.isSuccess() ? true : false;
        ThreadLocalMap.put(GlobalConstant.TLMK_SMS_FREQUENCY,msgSendSuccess);
        return result;
    }

    private Result handlerBizCheck(MsgBizEnum bizCode, String mobile) {
        boolean b = true;
        String errMsg = "";
        switch (bizCode) {
            case LOGIN:
                break;
            case REGISTER_USER:
                break;
            case RESET_PASSWORD:
                b = memberService.checkMobileExist(mobile);
                errMsg = "该手机号未注册";

        }
        return b ? ResultUtil.success() : ResultUtil.error(errMsg);
    }

    /**
     * 方法描述:发送短信验证码
     *
     * @param mobile    手机号
     * @param imageCode 图形验证码
     * @param bizCode  业务代码
     * @param request  HttpServletRequest
     * @return 结果
     */
    private Result sendMsg(String mobile, String imageCode, MsgBizEnum bizCode, HttpServletRequest request) {
        // 校验图形验证码是否正确
        String key = GlobalConstant.REDIS_PRE_CODE + request.getHeader(GlobalConstant.FIELD_UTOKEN);
        String verifyCode_redis = stringRedisTemplate.opsForValue().get(key);
        if (StringUtils.isBlank(verifyCode_redis)) {
            return ResultUtil.error(ResultCodeEnum.CODE_10011007);
        }
        if (imageCode.equalsIgnoreCase(verifyCode_redis)) {
            // 校验通过清除redis
            stringRedisTemplate.delete(key);
        } else {
            return ResultUtil.error(ResultCodeEnum.CODE_10011005);
        }
        // 生成验证码
        String verifyCode = CommonUtil.genVerifyCode(6);
        SmsParam param = new VerifyCodeParam(verifyCode);
        Msg msg = new Msg(bizCode, mobile, param);
        MsgResult response = MsgUtil.sendMsg(msg);
        if (response.isSuccess()) {
            String smsKey = GlobalConstant.REDIS_PRE_SMS + mobile;
            // 有效期10分钟
            stringRedisTemplate.opsForValue().set(smsKey, verifyCode, 10, TimeUnit.MINUTES);

        }
        return response.isSuccess() ? ResultUtil.success() : ResultUtil.error();
    }

    /**
     * 会员注册
     * @param registerDto 注册参数
     * @return  结果
     */
    @PostMapping("register")
    @NoNeedAccess
    public Result register(@RequestBody RegisterDto registerDto) {
        Long agentId = null;
        // 判断手机号是否已注册
        if (memberService.checkMobileExist(registerDto.getMobile())) {
            return ResultUtil.error(ResultCodeEnum.CODE_10012004);
        }
        // 校验短信验证码
        String key = GlobalConstant.REDIS_PRE_SMS + registerDto.getMobile();
        String verifyCode = stringRedisTemplate.opsForValue().get(key);
        if (StringUtil.isBlank(verifyCode)) {
            // 短信验证码已过期
            return ResultUtil.error(ResultCodeEnum.CODE_10011007);
        } else if (!registerDto.getSmsCode().equals(verifyCode)) {
            // 短信验证码验证失败
            return ResultUtil.error(ResultCodeEnum.CODE_10011005);
        }
        Result<SysConfigVo> result = sysConfigService.getByCode(SysCfgCodeEnum.MEMBER_BIND_AGENT.getCode());
        // 代理绑定开启
        String agentFlag = registerDto.getAgentFlag();
        if (result.isSuccess() && 1 == result.getData().getCfgValue() && StringUtils.isNotBlank(agentFlag)) {
            Result<AgentVo> agentVoResult;
            if (agentFlag.matches(GlobalConstant.REGEX_MOBILE)) {
                agentVoResult = agentServiceRpc.findByMobile(agentFlag);
            } else {
                agentVoResult = agentServiceRpc.findByAgentSn(agentFlag);
            }
            if (agentVoResult.isSuccess()) {
                AgentVo agent = agentVoResult.getData();
                if (IsEnableEnum.DISABLE == agent.getIsEnable()) {
                    return ResultUtil.error("代理商已禁用，不可绑定");
                } else {
                    agentId = agent.getId();
                }
            } else {
                // 调用代理商系统时发生异常
                return ResultUtil.error("查询代理商信息时发生异常，请稍后重试！");
            }
        }
        // 保存用户
        memberService.register(registerDto, agentId);
        return ResultUtil.success();
    }


    /**
     * 根据手机号重置密码
     * @param resetPwdDto 重置参数
     * @return 结果
     */
    @PostMapping("resetPwdByMobile")
    @NoNeedAccess
    public Result resetPassword(@RequestBody ResetPwdDto resetPwdDto) {
        // 校验手机号是否已注册
        if (!memberService.checkMobileExist(resetPwdDto.getMobile())) {
            return ResultUtil.error(ResultCodeEnum.CODE_10012007);
        }
        // 校验短信验证码
        String key = GlobalConstant.REDIS_PRE_SMS + resetPwdDto.getMobile();
        String verifyCode = stringRedisTemplate.opsForValue().get(key);
        if (StringUtil.isBlank(verifyCode)) {
            // 短信验证码已过期
            return ResultUtil.error(ResultCodeEnum.CODE_10011007);
        } else if (!resetPwdDto.getSmsCode().equals(verifyCode)) {
            // 短信验证码验证失败
            return ResultUtil.error(ResultCodeEnum.CODE_10011005);
        }
        if (!resetPwdDto.getPassword().equals(resetPwdDto.getConfirmPassword())) {
            return ResultUtil.error(ResultCodeEnum.CODE_10012008);
        }
        memberService.resetPwd(resetPwdDto.getMobile(), resetPwdDto.getPassword());
        return ResultUtil.success();
    }

    /**
     * 校验原密码
     *
     * @param oldPwd  原密码
     * @return 校验结果
     */
    @PostMapping("checkPwd")
    public Result checkPwd( @RequestBody String oldPwd) {
        MemAuth auth = AuthUtil.getMemberExt();
        Member member = memberService.getById(auth.getMid());
        if (CommonUtil.bCryptCheck(oldPwd, member.getPassword())) {
            return ResultUtil.success("校验通过");
        } else {
            return ResultUtil.error("校验失败");
        }
    }

    /**
     * 根据老密码重置密码
     *
     * @param dto  参数
     * @return  结果
     */
    @PostMapping("resetPwd")
    public Result resetPwd(@RequestBody MemberChgPwdDto dto) {
        MemAuth auth = AuthUtil.getMemberExt();
        Member member = memberService.getById(auth.getMid());
        if (!CommonUtil.bCryptCheck(dto.getOldPwd(), member.getPassword())) {
            return ResultUtil.success("原密码校验失败");
        }
        String newPwd = CommonUtil.encryptPassword(dto.getNewPwd());
        memberService.updatePassword(member.getId(), newPwd);
        return ResultUtil.success();
    }
}
